﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System;
using UnityEngine.UI;

namespace Model
{

  [CustomEditor(typeof(ReferenceMessager))]
  public class ReferenceEditor : Editor
  {
    private ReferenceMessager rm;

    private enum EAddType
    {
      标记,
      Button,
      Input,
    }

    ReorderableList list;

    EAddType addType = EAddType.标记;

    public void OnEnable()
    {
      this.rm = (ReferenceMessager)target;

      list = new ReorderableList(serializedObject, serializedObject.FindProperty("referenceList"), true, true, true, true);

      list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
        {
          var element = list.serializedProperty.GetArrayElementAtIndex(index);
          rect.y += 2;
          EditorGUI.PropertyField(new Rect(rect.x, rect.y, 150, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("key"), GUIContent.none);
          EditorGUI.PropertyField(new Rect(rect.x + 160, rect.y, rect.width - 160 - 40, EditorGUIUtility.singleLineHeight),
          element.FindPropertyRelative("reference"), GUIContent.none);
        };
      list.drawHeaderCallback = (Rect rect) =>
      {
        GUI.Label(rect, "    引用名 :                             引用对象 :");
      };

    }

    string tagName = "@";
    public override void OnInspectorGUI()
    {

      #region 添加引用
      EditorGUILayout.Space();
      EditorGUILayout.Space();
      EditorGUILayout.BeginHorizontal();
      addType = (EAddType)EditorGUILayout.EnumPopup("添加类型:", addType);
      EditorGUILayout.EndHorizontal();

      EditorGUILayout.BeginHorizontal();
      switch (addType)
      {
        case EAddType.标记:
          GUIStyle myStyle = new GUIStyle();
          myStyle.fontSize = 22;
          EditorGUILayout.LabelField("标记名:", GUILayout.Width(50), GUILayout.Height(20));
          tagName = EditorGUILayout.TextField(tagName, GUILayout.Height(20));
          if (GUILayout.Button("添加被标记的对象", GUILayout.Height(20)))
          {
            AddTagReference(tagName);
          }
          break;
        case EAddType.Button:
          if (GUILayout.Button("添加所有Button", GUILayout.Height(20)))
          {
            this.AddReference<Button>();
          }
          break;
        case EAddType.Input:
          if (GUILayout.Button("添加所有Input", GUILayout.Height(20)))
          {
            this.AddReference<InputField>();
          }
          break;

        default:
          break;
      }
      EditorGUILayout.EndHorizontal();

      EditorGUILayout.Space();
      EditorGUILayout.Space();

      EditorGUILayout.BeginHorizontal();

      if (GUILayout.Button("添加引用", GUILayout.Height(25)))
      {
        rm.referenceList.Add(new ReferenceData());
      }

      if (GUILayout.Button("删除空引用", GUILayout.Height(25)))
      {
        for (int i = rm.referenceList.Count; i > 0; i--)
        {
          var item = rm.referenceList[i - 1];
          if (item.reference == null) rm.referenceList.Remove(item);
        }
      }

      if (GUILayout.Button("删除所有引用", GUILayout.Height(25)))
      {
        if (EditorUtility.DisplayDialog("警告", "是否要删除所有引用？", "是", "否"))
        {
          rm.referenceList.Clear();
        }

      }

      EditorGUILayout.EndHorizontal();

      foreach (var item in rm.referenceList)
      {
        if (item.reference == null) continue;
        if (string.IsNullOrEmpty(item.key))
        {
          string refName = item.reference.name;
          item.key = refName.Replace(" ", "").Replace("(", "_").Replace(")", "_");
        }
      }
      #endregion





      serializedObject.Update();
      list.DoLayoutList();
      serializedObject.ApplyModifiedProperties();

    }



    private void AddReference<T>() where T : MonoBehaviour
    {
      T[] tmpObj = rm.GetComponentsInChildren<T>();
      foreach (var item in tmpObj)
      {
        bool tmpBool = true;
        foreach (var tmp in rm.referenceList)
        {
          T thisGo = item as T;
          if (tmp.reference is GameObject)
          {
            GameObject tmpGO = tmp.reference as GameObject;

            if (thisGo.gameObject == tmpGO)
            {
              tmpBool = false;
              break;
            }
          }
          else
          {
            T tmpGo = tmp.reference as T;
            if (tmpGo == null) continue;
            if (tmpGo.gameObject == thisGo.gameObject)
            {
              tmpBool = false;
              break;
            }
          }
        }
        if (tmpBool)
          rm.referenceList.Add(new ReferenceData((T)item));
      }
    }

    private void AddTagReference(string tag)
    {
      Transform[] tmpObj = rm.GetComponentsInChildren<Transform>();
      foreach (var item in tmpObj)
      {
        try
        {
          var index = item.gameObject.name.IndexOf(tag, 0, tag.Length);
          if (index != -1)
          {
            bool tmpBool = true;
            Transform thisGo = item as Transform;
            foreach (var tmp in rm.referenceList)
            {
              if (tmp.reference is GameObject)
              {
                GameObject tmpGO = tmp.reference as GameObject;

                if (thisGo.gameObject == tmpGO)
                {
                  tmpBool = false;
                  break;
                }
              }
              else
              {
                if (tmp.reference is Button)
                {
                  var tmpComponent = tmp.reference as Button;
                  if (tmpComponent.gameObject == thisGo.gameObject)
                  {
                    tmpBool = false;
                    break;
                  }
                }
                if (tmp.reference is InputField)
                {
                  var tmpComponent = tmp.reference as InputField;
                  if (tmpComponent.gameObject == thisGo.gameObject)
                  {
                    tmpBool = false;
                    break;
                  }
                }
              }
            }
            if (tmpBool)
            {
              rm.referenceList.Add(new ReferenceData(item.gameObject));
            }
          }
        }
        catch (Exception)
        {
        }

      }
    }


  }

}
